iT邦幫忙

2022 iThome 鐵人賽

DAY 20
0
Modern Web

React 新手村 - 填坑記系列 第 20

React 新手村 - 填坑記 - Day20 底層知識(三)

  • 分享至 

  • xImage
  •  

React版本優化小細節

React 渲染頁面的兩個階段

  • 調度階段(reconciliation):此階段 React 會更新數據生成新的 Virtual DOM,然後通過 Diff 算法,快速找出需要更新的元素,放到更新隊列中以此獲得新的更新隊列。
  • 渲染階段(commit):此階段會遍歷更新隊列,將其所有的變更一次性更新到 DOM 上。

React 15 架構

React15 架構可以分爲兩層:

  • Reconciler(協調器)—— 負責找出變化的組件;
  • Renderer(渲染器)—— 負責將變化的組件渲染到頁面上;

React15 及以前,Reconciler 採用遞歸的方式創建虛擬 DOM,遞歸過程是不能中斷的。如果component tree層級很深,遞歸會佔用線程很多時間,遞歸更新時間超過了 16ms,用戶交互就會卡頓。

而爲了解決這個問題,React16 將遞歸的無法中斷的更新重構爲異步的可中斷更新,同時也因為遞歸的虛擬 DOM 數據結構無法滿足整體架構,藉此使得全新的 Fiber 架構應運而生

React 16 架構

爲了解決同步更新長時間佔用線程導致頁面卡頓的問題,也爲了探索運行時優化的更多可能,React 開始重構並一直持續至今。重構的目標是實現 Concurrent Mode(併發模式)。

從 v15 到 v16,React 團隊花了兩年時間將源碼架構中的 Stack Reconciler 重構爲 Fiber Reconciler。
React16 架構可以分爲三層:

  • Scheduler(調度器)—— 調度任務的優先級,高優任務優先進入 Reconciler;
  • Reconciler(協調器)—— 負責找出變化的組件:更新工作從遞歸變成了可以中斷的循環過程。Reconciler 內部採用了 Fiber 的架構;
  • Renderer(渲染器)—— 負責將變化的組件渲染到頁面上。

React 17 架構

React16 的 expirationTimes 模型只能區分是否>=expirationTimes決定節點是否更新。
React17 的 lanes 模型可以選定一個更新區間,並且動態的向區間中增減優先級,可以處理更細粒度的更新。

Lanes 用二進制位表示任務的優先級,方便優先級的計算(位運算),不同優先級佔用不同位置的 “賽道”,而且存在批的概念,優先級越低,“賽道” 越多。高優先級打斷低優先級,新建的任務需要賦予什麼優先級等問題都是 Lane 所要解決的問題。

Concurrent Mode 的目的是實現一套可中斷 / 恢復的更新機制。其由兩部分組成:

  • 一套協程架構:Fiber Reconciler
  • 基於協程架構的啓發式更新算法:控制協程架構工作方式的算法

React 18 架構

concurrent(並行)功能部份

startTransition()
useTransition(): 類似於節流閥(Throttling)與防抖動(debouncing)的機制,但由 React 來控管更新的時間點
useDeferredValue(): 與 useTransition 類似機制,但用於從父母元件接收新值(useTransition 用於事件處理器觸發更新)
註: 更多相關內容可參考New feature: startTransition與New in 18: useDeferredValue

針對函式庫開發者部份

useId(): "不是"用來產生列表項目的 key,之前名稱為 useOpaqueIdentifier,目的是能同時在客戶端與伺服器端產生唯一 ID,避免伺服器端渲染(SSR)的事件處理器水合作用匹配上的問題。
useSyncExternalStore(): 主要針對外部狀態函式庫開發使用,如 redux, mobx, zustand 等等
useInsertionEffect(): 主要針對給 css-in-js 函式庫開發使用。(應用開發建議優先使用 useEffect 或 useLayoutEffect)


上一篇
React 新手村 - 填坑記 - Day19 底層知識(二)
下一篇
React 新手村 - 填坑記 - Day21 常見錯誤(一)
系列文
React 新手村 - 填坑記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言